!===============================================================================
! SVN: $Id: shr_strdata.F90 11584 2008-09-08 03:16:24Z mvertens $
! SVN: $HeadURL: https://svn-ccsm-models.cgd.ucar.edu/dlnd7/trunk_tags/dlnd7_090320/shr_strdata.F90 $
!===============================================================================
!BOP ===========================================================================
!
! !MODULE: shr_strdata_mod -- holds data and methods to advance data models
!
! !DESCRIPTION:
!    holds data and methods to advance data models
!
! !REVISION HISTORY:
!    2009-Apr-15 - T. Craig initial version
!
! !INTERFACE: ------------------------------------------------------------------

module shr_strdata_mod

   use shr_const_mod, only: SHR_CONST_PI
   use shr_kind_mod, only: IN=>SHR_KIND_IN, R8=>SHR_KIND_R8, &
                           CS=>SHR_KIND_CS, CL=>SHR_KIND_CL, &
                           CX=>SHR_KIND_CX
   use shr_sys_mod, only : shr_sys_abort, shr_sys_flush
   use shr_mpi_mod, only : shr_mpi_bcast
   use shr_file_mod, only : shr_file_getunit, shr_file_freeunit
   use shr_log_mod, only: loglev  => shr_log_Level
   use shr_log_mod, only: logunit => shr_log_Unit
   use shr_stream_mod  ! stream data type and methods
   use shr_string_mod
   use shr_map_mod
   use shr_cal_mod, only: shr_cal_date2eday,shr_cal_calendarname, &
                          shr_cal_noleap, shr_cal_gregorian, &
                          shr_cal_date2ymd, shr_cal_ymd2date
   use shr_orb_mod, only: shr_orb_decl, shr_orb_cosz, shr_orb_undef_real
   use shr_tinterp_mod

   use shr_dmodel_mod    ! shr data model stuff

   use shr_mct_mod
   use mct_mod         ! mct
   use perf_mod        ! timing
   use pio             ! pio

   implicit none

   private

! !PUBLIC TYPES:

   public shr_strdata_type

! !PUBLIC MEMBER FUNCTIONS:

   public shr_strdata_readnml
   public shr_strdata_bcastnml
   public shr_strdata_restRead
   public shr_strdata_restWrite
   public shr_strdata_setOrbs
   public shr_strdata_print
   public shr_strdata_init
   public shr_strdata_create
   public shr_strdata_advance
   public shr_strdata_clean
   public shr_strdata_setlogunit
   public shr_strdata_pioinit

! !PUBLIC DATA MEMBERS:


! !PRIVATE:

  integer(IN),parameter :: nStrMax = 30
  integer(IN),parameter :: nVecMax = 30
  character(len=*),public,parameter :: shr_strdata_nullstr = 'null'
  character(len=*),parameter :: shr_strdata_unset = 'NOT_SET'
  real(R8),parameter,private :: dtlimit_default = 1.5_R8

  type shr_strdata_type
    ! --- set by input ---
    character(CL) :: dataMode          ! flags physics options wrt input data
    character(CL) :: domainFile        ! file   containing domain info
    character(CL) :: streams (nStrMax) ! stream description file names
    character(CL) :: taxMode (nStrMax) ! time axis cycling mode
    real(R8)      :: dtlimit (nStrMax) ! dt max/min limit
    character(CL) :: vectors (nVecMax) ! define vectors to vector map
    character(CL) :: fillalgo(nStrMax) ! fill algorithm
    character(CL) :: fillmask(nStrMax) ! fill mask
    character(CL) :: fillread(nStrMax) ! fill mapping file to read
    character(CL) :: fillwrit(nStrMax) ! fill mapping file to write
    character(CL) :: mapalgo (nStrMax) ! scalar map algorithm
    character(CL) :: mapmask (nStrMax) ! scalar map mask
    character(CL) :: mapread(nStrMax)  ! regrid mapping file to read
    character(CL) :: mapwrit(nStrMax)  ! regrid mapping file to write
    character(CL) :: tintalgo(nStrMax) ! time interpolation algorithm
    integer(IN)   :: io_type
    !--- data required by cosz t-interp method, set by user ---
    real(R8)      :: eccen
    real(R8)      :: mvelpp
    real(R8)      :: lambm0
    real(R8)      :: obliqr
    integer(IN)   :: modeldt ! model dt in seconds
    ! --- internal, public ---
    integer(IN)   :: nxg
    integer(IN)   :: nyg
    integer(IN)   :: lsize
    type(mct_gsmap) :: gsmap
    type(mct_ggrid) :: grid
    type(mct_avect) :: avs(nStrMax)
    ! --- internal ---
    type(shr_stream_streamType) :: stream(nStrMax)
    type(iosystem_desc_t), pointer       :: pio_subsystem
    type(io_desc_t)             :: pio_iodesc(nStrMax)
    integer(IN)     :: nstreams      ! number of streams
    integer(IN)     :: strnxg(nStrMax)
    integer(IN)     :: strnyg(nStrMax)
    logical         :: dofill(nStrMax)
    logical         :: domaps(nStrMax)
    integer(IN)     :: lsizeR(nStrMax)
    type(mct_gsmap) :: gsmapR(nStrMax)
    type(mct_rearr) :: rearrR(nStrMax)
    type(mct_ggrid) :: gridR(nStrMax)
    type(mct_avect) :: avRLB(nStrMax)
    type(mct_avect) :: avRUB(nStrMax)
    type(mct_avect) :: avFUB(nStrMax)
    type(mct_avect) :: avFLB(nStrMax)
    type(mct_avect) :: avCoszen(nStrMax)    ! data assocaited with coszen time interp
    type(mct_sMatP) :: sMatPf(nStrMax)
    type(mct_sMatP) :: sMatPs(nStrMax)
    integer(IN)     :: ymdLB(nStrMax),todLB(nStrMax)
    integer(IN)     :: ymdUB(nStrMax),todUB(nStrMax)
    real(R8)        :: dtmin(nStrMax)
    real(R8)        :: dtmax(nStrMax)
    integer(IN)     :: ymd  ,tod
    character(CL)   :: calendar          ! model calendar for ymd,tod
    integer(IN)     :: nvectors          ! number of vectors
    integer(IN)     :: ustrm (nVecMax)
    integer(IN)     :: vstrm (nVecMax)
    character(CL)   :: allocstring
  end type shr_strdata_type

  real(R8),parameter,private :: deg2rad = SHR_CONST_PI/180.0_R8
  character(len=*),parameter :: allocstring_value = 'strdata_allocated'

!===============================================================================
  contains
!===============================================================================

  subroutine shr_strdata_init(SDAT,mpicom,compid,name,scmmode,scmlon,scmlat, &
                              gsmap,ggrid,nxg,nyg,calendar)

  implicit none

  type(shr_strdata_type),intent(inout) :: SDAT
  integer(IN)           ,intent(in)    :: mpicom
  integer(IN)           ,intent(in)    :: compid
  character(len=*)      ,intent(in),optional :: name
  logical               ,intent(in),optional :: scmmode
  real(R8)              ,intent(in),optional :: scmlon
  real(R8)              ,intent(in),optional :: scmlat
  type(mct_gsmap)       ,intent(in),optional :: gsmap
  type(mct_ggrid)       ,intent(in),optional :: ggrid
  integer(IN)           ,intent(in),optional :: nxg
  integer(IN)           ,intent(in),optional :: nyg
  character(len=*)      ,intent(in),optional :: calendar

  integer(IN) :: n,m,k         ! generic index
  integer(IN) :: nu,nv         ! u,v index
  integer(IN) :: my_task,npes  ! my task, total pes
  integer(IN),parameter :: master_task = 0
  character(CS) :: lname       ! local name
  character(CL) :: filePath    ! generic file path
  character(CL) :: fileName    ! generic file name
  character(CS) :: timeName    ! domain file: time variable name
  character(CS) ::  lonName    ! domain file: lon  variable name
  character(CS) ::  latName    ! domain file: lat  variable name
  character(CS) :: maskName    ! domain file: mask variable name
  character(CS) :: areaName    ! domain file: area variable name
  character(CS) :: uname       ! u vector field name
  character(CS) :: vname       ! v vector field name
  character(CX) :: fldList     ! list of fields
  integer(IN)   :: lsize
  integer(IN)   :: nfiles
  integer(IN)   :: ierr
  integer(IN)   :: method
  integer(IN), pointer :: dof(:)
  type(mct_sMat):: sMati
  logical       :: lscmmode

  character(len=*),parameter :: subname = "(shr_strdata_init) "
  character(*),parameter ::   F00 = "('(shr_strdata_init) ',8a)" 

!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------

  call MPI_COMM_SIZE(mpicom,npes,ierr)
  call MPI_COMM_RANK(mpicom,my_task,ierr)
  !--- Count streams again in case user made changes ---
  if (my_task == master_task) then
     do n=1,nStrMax
        !--- check if a streams string is defined in strdata
        if (trim(SDAT%streams(n)) /= trim(shr_strdata_nullstr)) SDAT%nstreams = max(SDAT%nstreams,n)
        !--- check if a filename is defined in the stream
        call shr_stream_getNFiles(SDAT%stream(n),nfiles)
        if (nfiles > 0) SDAT%nstreams = max(SDAT%nstreams,n)

        if (trim(SDAT%taxMode(n)) == trim(shr_stream_taxis_extend)) SDAT%dtlimit(n) = 1.0e30
     end do
     SDAT%nvectors = 0
     do n=1,nVecMax
        if (trim(SDAT%vectors(n)) /= trim(shr_strdata_nullstr)) SDAT%nvectors = n
     end do
  endif

  call shr_mpi_bcast(SDAT%nstreams  ,mpicom,'nstreams')
  call shr_mpi_bcast(SDAT%nvectors  ,mpicom,'nvectors')
  call shr_mpi_bcast(SDAT%dtlimit   ,mpicom,'dtlimit')

  if (SDAT%nstreams < 1) return

  n = 0
  if (present(gsmap)) then
     n = n + 1
  endif
  if (present(ggrid)) then
     n = n + 1
  endif
  if (present(nxg)) then
     n = n + 1
  endif
  if (present(nyg)) then
     n = n + 1
  endif

  if ( n == 0 .or. n == 4) then
     ! either all set or none set, this is OK
  else
     write(logunit,*) subname,' ERROR: gsmap, ggrid, nxg, and nyg  must be specified together'
     call shr_sys_abort(subname//' ERROR: gsmap, ggrid, nxg, nyg  set together')
  endif

  lscmmode = .false.
  if (present(scmmode)) then
     lscmmode = scmmode
     if (lscmmode) then
        if (.not.present(scmlon) .or. .not.present(scmlat)) then
           write(logunit,*) subname,' ERROR: scmmode requires scmlon and scmlat'
           call shr_sys_abort(subname//' ERROR: scmmode1 lon lat')
        endif
     endif
  endif

  lname = ""
  if (present(name)) then
     lname = "_"//trim(name)
  endif

  if (present(calendar)) then
     SDAT%calendar = trim(shr_cal_calendarName(trim(calendar)))
  endif

  ! --- initialize streams and stream domains ---


  do n = 1,SDAT%nstreams
     if (my_task == master_task) then
        call shr_stream_getDomainInfo(SDAT%stream(n),filePath,fileName,timeName,lonName, &
             latName,maskName,areaName)
        call shr_stream_getFile(filePath,fileName)
      endif
      call shr_mpi_bcast(fileName,mpicom)
      call shr_mpi_bcast(lonName,mpicom)
      call shr_mpi_bcast(latName,mpicom)
      call shr_mpi_bcast(maskName,mpicom)
      call shr_mpi_bcast(areaName,mpicom)
      call shr_dmodel_readgrid(SDAT%gridR(n),SDAT%gsmapR(n),SDAT%strnxg(n),SDAT%strnyg(n), &
           fileName, compid, mpicom, '1d', lonName, latName, maskName, areaName)
      SDAT%lsizeR(n) = mct_gsmap_lsize(SDAT%gsmapR(n),mpicom)
      call mct_gsmap_OrderedPoints(SDAT%gsmapR(n), my_task, dof)
      call pio_initdecomp(SDAT%pio_subsystem, pio_double, &
           (/SDAT%strnxg(n),SDAT%strnyg(n)/), dof, SDAT%pio_iodesc(n))
      deallocate(dof)

      call shr_mpi_bcast(SDAT%stream(n)%calendar,mpicom)
  enddo

  ! --- initialize model domain ---

  if (present(gsmap)) then
     SDAT%nxg = nxg
     SDAT%nyg = nyg
     lsize = mct_gsmap_lsize(gsmap,mpicom)
     call mct_gsmap_Copy(gsmap,SDAT%gsmap)
     call mct_ggrid_init(SDAT%grid, ggrid, lsize)    
     call mct_aVect_copy(ggrid%data, SDAT%grid%data)
  else
     if (trim(SDAT%domainfile) == trim(shr_strdata_nullstr)) then
        if (SDAT%nstreams > 0) then
           if (my_task == master_task) then
              call shr_stream_getDomainInfo(SDAT%stream(1),filePath,fileName,timeName,lonName, &
                      latName,maskName,areaName)
              call shr_stream_getFile(filePath,fileName)
           endif
           call shr_mpi_bcast(fileName,mpicom)
           call shr_mpi_bcast(lonName,mpicom)
           call shr_mpi_bcast(latName,mpicom)
           call shr_mpi_bcast(maskName,mpicom)
           call shr_mpi_bcast(areaName,mpicom)
           if (lscmmode) then
              call shr_dmodel_readgrid(SDAT%grid,SDAT%gsmap,SDAT%nxg,SDAT%nyg, &
                   fileName, compid, mpicom, '1d', lonName, latName, maskName, areaName, &
                   scmmode=lscmmode,scmlon=scmlon,scmlat=scmlat)
           else
              call shr_dmodel_readgrid(SDAT%grid,SDAT%gsmap,SDAT%nxg,SDAT%nyg, &
                   fileName, compid, mpicom, '1d', lonName, latName, maskName, areaName)
          endif
        endif
     else
         if (lscmmode) then
            call shr_dmodel_readgrid(SDAT%grid,SDAT%gsmap,SDAT%nxg,SDAT%nyg, &
                 SDAT%domainfile, compid, mpicom, '1d', readfrac=.true., &
                 scmmode=lscmmode,scmlon=scmlon,scmlat=scmlat)
         else
            call shr_dmodel_readgrid(SDAT%grid,SDAT%gsmap,SDAT%nxg,SDAT%nyg, &
                 SDAT%domainfile, compid, mpicom, '1d', readfrac=.true.)
         endif
     endif
  endif
  SDAT%lsize = mct_gsmap_lsize(SDAT%gsmap,mpicom)

  ! --- setup mapping ---

  do n = 1,SDAT%nstreams
     if (shr_dmodel_gGridCompare(SDAT%gridR(n),SDAT%gsmapR(n),SDAT%grid,SDAT%gsmap, &
         shr_dmodel_gGridCompareMaskSubset,mpicom) .or. trim(SDAT%fillalgo(n))=='none') then
        SDAT%dofill(n) = .false.
     else
        SDAT%dofill(n) = .true.
     endif
     if (trim(SDAT%mapmask(n)) == 'dstmask') then
        method = shr_dmodel_gGridCompareXYabsMask
     else
        method = shr_dmodel_gGridCompareXYabs
     endif
     if (shr_dmodel_gGridCompare(SDAT%gridR(n),SDAT%gsmapR(n),SDAT%grid,SDAT%gsmap, &
         method,mpicom,0.01_r8) .or. trim(SDAT%mapalgo(n))=='none') then
        SDAT%domaps(n) = .false.
     else
        SDAT%domaps(n) = .true.
     endif

     if (SDAT%dofill(n)) then
        if (trim(SDAT%fillread(n)) == trim(shr_strdata_unset)) then
           if (my_task == master_task) then
             write(logunit,F00) ' calling shr_dmodel_mapSet for fill'
             call shr_sys_flush(logunit)
           endif
           call shr_dmodel_mapSet(SDAT%sMatPf(n), &
             SDAT%gridR(n),SDAT%gsmapR(n),SDAT%strnxg(n),SDAT%strnyg(n), &
             SDAT%gridR(n),SDAT%gsmapR(n),SDAT%strnxg(n),SDAT%strnyg(n), &
             name='mapFill', type='cfill', &
             algo=trim(SDAT%fillalgo(n)),mask=trim(SDAT%fillmask(n)),vect='scalar', &
             compid=compid,mpicom=mpicom)
           if (trim(SDAT%fillwrit(n)) /= trim(shr_strdata_unset)) then
             if (my_task == master_task) then
               write(logunit,F00) ' writing ',trim(SDAT%fillwrit(n))
               call shr_sys_flush(logunit)
             endif
             call shr_mct_sMatWritednc(SDAT%sMatPf(n)%Matrix,SDAT%pio_subsystem,sdat%io_type,  SDAT%fillwrit(n),compid,mpicom)
           endif
        else
           if (my_task == master_task) then
             write(logunit,F00) ' reading ',trim(SDAT%fillread(n))
             call shr_sys_flush(logunit)
           endif
           call shr_mct_sMatReaddnc(sMati,SDAT%gsmapR(n),SDAT%gsmapR(n),'src', &
             filename=trim(SDAT%fillread(n)),mytask=my_task,mpicom=mpicom)
           call mct_sMatP_Init(SDAT%sMatPf(n),sMati,SDAT%gsMapR(n),SDAT%gsmapR(n),0, mpicom, compid)
           call mct_sMat_Clean(sMati)
        endif
     endif
     if (SDAT%domaps(n)) then
        if (trim(SDAT%mapread(n)) == trim(shr_strdata_unset)) then
           if (my_task == master_task) then
             write(logunit,F00) ' calling shr_dmodel_mapSet for remap'
             call shr_sys_flush(logunit)
           endif
           call shr_dmodel_mapSet(SDAT%sMatPs(n), &
             SDAT%gridR(n),SDAT%gsmapR(n),SDAT%strnxg(n),SDAT%strnyg(n), &
             SDAT%grid ,SDAT%gsmap ,SDAT%nxg      ,SDAT%nyg, &
             name='mapScalar', type='remap', &
             algo=trim(SDAT%mapalgo(n)),mask=trim(SDAT%mapmask(n)), vect='scalar', &
             compid=compid,mpicom=mpicom)
           if (trim(SDAT%mapwrit(n)) /= trim(shr_strdata_unset)) then
             if (my_task == master_task) then
               write(logunit,F00) ' writing ',trim(SDAT%mapwrit(n))
               call shr_sys_flush(logunit)
             endif
             call shr_mct_sMatWritednc(SDAT%sMatPs(n)%Matrix,sdat%pio_subsystem,sdat%io_type,SDAT%mapwrit(n),compid,mpicom)
           endif
        else
           if (my_task == master_task) then
             write(logunit,F00) ' reading ',trim(SDAT%mapread(n))
             call shr_sys_flush(logunit)
           endif
           call shr_mct_sMatReaddnc(sMati,SDAT%gsmapR(n),SDAT%gsmap,'src', &
             filename=trim(SDAT%mapread(n)),mytask=my_task,mpicom=mpicom)
           call mct_sMatP_Init(SDAT%sMatPs(n),sMati,SDAT%gsMapR(n),SDAT%gsmap,0, mpicom, compid)
           call mct_sMat_Clean(sMati)
        endif
     else
        call mct_rearr_init(SDAT%gsmapR(n), SDAT%gsmap, mpicom, SDAT%rearrR(n))
     endif
  enddo

  ! --- setup datatypes ---

  do n = 1,SDAT%nstreams
     if (my_task == master_task) then
        call shr_stream_getModelFieldList(SDAT%stream(n),fldList)
     endif
     call shr_mpi_bcast(fldList,mpicom)
     call mct_aVect_init(SDAT%avs(n)  ,rlist=fldList,lsize=SDAT%lsize)
     call mct_aVect_init(SDAT%avFLB(n),rlist=fldList,lsize=SDAT%lsize)
     call mct_aVect_init(SDAT%avFUB(n),rlist=fldList,lsize=SDAT%lsize)
     call mct_aVect_init(SDAT%avRLB(n),rlist=fldList,lsize=SDAT%lsizeR(n))
     call mct_aVect_init(SDAT%avRUB(n),rlist=fldList,lsize=SDAT%lsizeR(n))
     if (trim(SDAT%tintalgo(n)) == 'coszen') then
        call mct_aVect_init(SDAT%avCoszen(n),rlist="tavCosz",lsize=SDAT%lsize)
     endif
  enddo

  ! --- check vectors and compute ustrm,vstrm ---

  do m = 1,SDAT%nvectors
     if (.not. shr_string_listIsValid(SDAT%vectors(m))) then
        write(logunit,*) trim(subname),' vec fldlist invalid m=',m,trim(SDAT%vectors(m))
        call shr_sys_abort(subname//': vec fldlist invalid:'//trim(SDAT%vectors(m)))
     endif
     if (shr_string_listGetNum(SDAT%vectors(m)) /= 2) then
        write(logunit,*) trim(subname),' vec fldlist ne 2 m=',m,trim(SDAT%vectors(m))
        call shr_sys_abort(subname//': vec fldlist ne 2:'//trim(SDAT%vectors(m)))
     endif
     call shr_string_listGetName(SDAT%vectors(m),1,uname)
     call shr_string_listGetName(SDAT%vectors(m),2,vname)
     nu = 0
     nv = 0
     do n = 1,SDAT%nstreams
        k = mct_aVect_indexRA(SDAT%avRLB(n),trim(uname),perrWith='quiet')
        if (k > 0) nu = n
        k = mct_aVect_indexRA(SDAT%avRLB(n),trim(vname),perrWith='quiet')
        if (k > 0) nv = n
     enddo
     if (nu == 0  .or. nv == 0) then
        write(logunit,*) trim(subname),' vec flds not found  m=',m,trim(SDAT%vectors(m))
        call shr_sys_abort(subname//': vec flds not found:'//trim(SDAT%vectors(m)))
     endif
     if (nu /= nv) then
        if ((.not. shr_dmodel_gGridCompare(SDAT%gridR(nu),SDAT%gsmapR(nu), &
                                         SDAT%gridR(nv),SDAT%gsmapR(nv), &
                                         shr_dmodel_gGridCompareXYabs,mpicom,0.01_r8)) .or. &
            (.not. shr_dmodel_gGridCompare(SDAT%gridR(nu),SDAT%gsmapR(nu), &
                                         SDAT%gridR(nv),SDAT%gsmapR(nv), &
                                         shr_dmodel_gGridCompareMaskZeros,mpicom))) then
           write(logunit,*) trim(subname),' vec fld doms not same m=',m,trim(SDAT%vectors(m))
           call shr_sys_abort(subname//': vec fld doms not same:'//trim(SDAT%vectors(m)))
        endif
     endif
     SDAT%ustrm(m) = nu
     SDAT%vstrm(m) = nv
  enddo

  end subroutine shr_strdata_init

!===============================================================================

  subroutine shr_strdata_advance(SDAT,ymd,tod,mpicom,istr,timers)

  implicit none

  type(shr_strdata_type),intent(inout) :: SDAT
  integer(IN),intent(in) :: ymd    ! current model date
  integer(IN),intent(in) :: tod    ! current model date
  integer(IN),intent(in) :: mpicom
  character(len=*),intent(in),optional :: istr
  logical         ,intent(in),optional :: timers

  integer(IN) :: n,m,i,k,l,kf           ! generic index
  integer(IN) :: my_task,npes
  integer(IN),parameter :: master_task = 0
  logical :: mssrmlf
  logical,allocatable :: newData(:)
  integer(IN) :: ierr
  integer(IN) :: nu,nv
  integer(IN) :: lsize,lsizeR,lsizeF
  integer(IN) :: ymdmod,todmod   ! modified model dates to handle Sept 29
  type(mct_avect) :: avRtmp
  type(mct_avect) :: avRV,avFV
  character(len=32) :: lstr
  logical  :: ltimers
  real(R8) :: flb,fub            ! factor for lb and ub

  !--- for cosz method ---
  real(R8) :: calday             ! julian day of year
  real(R8) :: declin             ! solar declination (radians)
  real(R8) :: eccf               ! earth sun distance factor
  real(R8),pointer :: lonr(:)    ! lon radians
  real(R8),pointer :: latr(:)    ! lat radians
  real(R8),pointer :: cosz(:)    ! cosz 
  real(R8),pointer :: tavCosz(:) ! cosz, time avg over [LB,UB]
  real(R8),pointer :: xlon(:),ylon(:)
  real(R8),parameter :: solZenMin    = 0.001_R8 ! minimum solar zenith angle

  integer(IN)   :: edayLB,edayUB ! elapsed days
  real(R8)      :: dtime         ! delta time
  integer(IN)   :: uvar,vvar
  logical       :: someNewData ! newData test
  character(CS) :: uname       ! u vector field name
  character(CS) :: vname       ! v vector field name
  integer(IN)   :: year,month,day  ! date year month day
  character(len=*),parameter :: timname = "_strd_adv"
  integer(IN),parameter :: tadj = 2

   !----- formats -----
  character(*),parameter :: subname = "(shr_strdata_advance) "

!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------

  if (SDAT%nstreams < 1) return

  lstr = ''
  if (present(istr)) then
    lstr = trim(istr)
  endif

  ltimers = .true.
  if (present(timers)) then
    ltimers = timers
  endif

  if (.not.ltimers) call t_adj_detailf(tadj)

  call MPI_COMM_SIZE(mpicom,npes,ierr)
  call MPI_COMM_RANK(mpicom,my_task,ierr)

  mssrmlf = .false.

  SDAT%ymd = ymd
  SDAT%tod = tod

  if (SDAT%nstreams > 0) then
  allocate(newData(SDAT%nstreams))

  do n = 1,SDAT%nstreams
     ! ------------------------------------------------------- !
     ! tcraig, Oct 11 2010.  Mismatching calendars: 4 cases    ! 
     ! ------------------------------------------------------- !
     ! ymdmod and todmod are the ymd and tod to time           !
     ! interpolate to.  Generally, these are just the model    !
     ! date and time.  Also, always use the stream calendar    !
     ! for time interpolation for reasons described below.     !
     ! When there is a calendar mismatch, support Feb 29 in a  !
     ! special way as needed to get reasonable values.         !
     ! Note that when Feb 29 needs to be treated specially,    !
     ! a discontinuity will be introduced.  The size of that   !
     ! discontinuity will depend on the time series input data.!
     ! ------------------------------------------------------- !
     ! (0) The stream calendar and model calendar are          !
     ! identical.  Proceed in the standard way.                !
     ! ------------------------------------------------------- !
     ! (1) If the stream is a no leap calendar and the model   !
     ! is gregorian, then time interpolate on the noleap       !
     ! calendar.  Then if the model date is Feb 29, compute    !
     ! stream data for Feb 28 by setting ymdmod and todmod to  !
     ! Feb 28.  This results in duplicate stream data on       !
     ! Feb 28 and Feb 29 and a discontinuity at the start of   !
     ! Feb 29.                                                 !
     ! This could be potentially updated by using the gregorian!
     ! calendar for time interpolation when the input data is  !
     ! relatively infrequent (say greater than daily) with the !
     ! following concerns.
     !   - The forcing will not be reproduced identically on   !
     !     the same day with climatological inputs data        !
     !   - Input data with variable input frequency might      !
     !     behave funny
     !   - An arbitrary discontinuity will be introduced in    !
     !     the time interpolation method based upon the        !
     !     logic chosen to transition from reproducing Feb 28  !
     !     on Feb 29 and interpolating to Feb 29.              !
     !   - The time gradient of data will change by adding a   !
     !     day arbitrarily.
     ! ------------------------------------------------------- !
     ! (2) If the stream is a gregorian calendar and the model !
     ! is a noleap calendar, then just time interpolate on the !
     ! gregorian calendar.  The causes Feb 29 stream data      !
     ! to be skipped and will lead to a discontinuity at the   !
     ! start of March 1.                                       !
     ! ------------------------------------------------------- !
     ! (3) If the calendars mismatch and neither of the three  !
     ! cases above are recognized, then abort.                 !
     ! ------------------------------------------------------- !

     ! case(0)
     ymdmod = ymd
     todmod = tod
     if (trim(SDAT%calendar) /= trim(SDAT%stream(n)%calendar)) then
        if ((trim(SDAT%calendar) == trim(shr_cal_gregorian)) .and. &
            (trim(SDAT%stream(n)%calendar) == trim(shr_cal_noleap))) then
            ! case (1), set feb 29 = feb 28
            call shr_cal_date2ymd (ymd,year,month,day)
            if (month == 2 .and. day == 29) then
               call shr_cal_ymd2date(year,2,28,ymdmod)
            endif
        else if ((trim(SDAT%calendar) == trim(shr_cal_noleap)) .and. &
            (trim(SDAT%stream(n)%calendar) == trim(shr_cal_gregorian))) then
            ! case (2), feb 29 input data will be skipped automatically
        else
            ! case (3), abort
            write(logunit,*) trim(subname),' ERROR: mismatch calendar ', &
               trim(SDAT%calendar),':',trim(SDAT%stream(n)%calendar)
            call shr_sys_abort(trim(subname)//' ERROR: mismatch calendar ')
        endif
     endif

     call t_barrierf(trim(lstr)//trim(timname)//'_readLBUB_BARRIER',mpicom)
     call t_startf(trim(lstr)//trim(timname)//'_readLBUB')

     call shr_dmodel_readLBUB(SDAT%stream(n),SDAT%pio_subsystem,SDAT%io_type,SDAT%pio_iodesc(n), &
          ymdmod,todmod,mpicom,SDAT%gsmapR(n),&
          SDAT%avRLB(n),SDAT%ymdLB(n),SDAT%todLB(n), &
          SDAT%avRUB(n),SDAT%ymdUB(n),SDAT%todUB(n),newData(n), &
          istr=trim(lstr)//'_readLBUB')
     if (newData(n)) then
        call shr_cal_date2eday(SDAT%ymdLB(n),edayLB,SDAT%stream(n)%calendar)
        call shr_cal_date2eday(SDAT%ymdUB(n),edayUB,SDAT%stream(n)%calendar)
        dtime = abs(real(edayUB-edayLB,R8) + real(SDAT%todUB(n)-SDAT%todLB(n),R8)/shr_const_cDay)
        SDAT%dtmin(n) = min(SDAT%dtmin(n),dtime)
        SDAT%dtmax(n) = max(SDAT%dtmax(n),dtime)
        if ((SDAT%dtmax(n)/SDAT%dtmin(n)) > SDAT%dtlimit(n)) then
           write(logunit,*) trim(subName),' ERROR: dt limit1 ',SDAT%dtmax(n),SDAT%dtmin(n),SDAT%dtlimit(n)
           write(logunit,*) trim(subName),' ERROR: dt limit2 ',SDAT%ymdLB(n),SDAT%todLB(n), &
                                                               SDAT%ymdUB(n),SDAT%todUB(n)
           call shr_sys_abort(trim(subName)//' ERROR dt limit')
        endif
     endif
     call t_stopf(trim(lstr)//trim(timname)//'_readLBUB')
  enddo

  do n = 1,SDAT%nstreams
     if (newData(n)) then

        if (SDAT%doFill(n)) then
           call t_startf(trim(lstr)//trim(timname)//'_fill')
           lsize = mct_aVect_lsize(SDAT%avRLB(n))
           call mct_aVect_init(avRtmp,SDAT%avRLB(n),lsize)
           call mct_aVect_copy(SDAT%avRLB(n),avRtmp)
           call mct_sMat_avMult(avRtmp,SDAT%sMatPf(n),SDAT%avRLB(n))
           call mct_aVect_copy(SDAT%avRUB(n),avRtmp)
           call mct_sMat_avMult(avRtmp,SDAT%sMatPf(n),SDAT%avRUB(n))
           call mct_aVect_clean(avRtmp)
           call t_stopf(trim(lstr)//trim(timname)//'_fill')
        endif

        if (SDAT%domaps(n)) then
           call t_startf(trim(lstr)//trim(timname)//'_map')
           call mct_sMat_avMult(SDAT%avRLB(n),SDAT%sMatPs(n),SDAT%avFLB(n))
           call mct_sMat_avMult(SDAT%avRUB(n),SDAT%sMatPs(n),SDAT%avFUB(n))
           call t_stopf(trim(lstr)//trim(timname)//'_map')
        else
           call t_startf(trim(lstr)//trim(timname)//'_rearr')
           call mct_rearr_rearrange(SDAT%avRLB(n),SDAT%avFLB(n),SDAT%rearrR(n))
           call mct_rearr_rearrange(SDAT%avRUB(n),SDAT%avFUB(n),SDAT%rearrR(n))
           call t_stopf(trim(lstr)//trim(timname)//'_rearr')
        endif

     endif
  enddo

  do m = 1,SDAT%nvectors
     nu = SDAT%ustrm(m)
     nv = SDAT%vstrm(m)
     if ((SDAT%domaps(nu) .or. SDAT%domaps(nv)) .and. &
         (newdata(nu) .or. newdata(nv))) then

        call t_startf(trim(lstr)//trim(timname)//'_vect')
        call shr_string_listGetName(SDAT%vectors(m),1,uname)
        call shr_string_listGetName(SDAT%vectors(m),2,vname)
        lsizeR = mct_aVect_lsize(SDAT%avRLB(nu))
        lsizeF = mct_aVect_lsize(SDAT%avFLB(nu))
        call mct_aVect_init(avRV,rlist=SDAT%vectors(m),lsize=lsizeR)
        call mct_aVect_init(avFV,rlist=SDAT%vectors(m),lsize=lsizeF)
        call mct_aVect_exportRattr(SDAT%gridR(nu)%data,'lon',xlon)
        call mct_aVect_exportRattr(SDAT%grid  %data,'lon',ylon)
        xlon = xlon * deg2rad
        ylon = ylon * deg2rad

        !--- map LB ---

        uvar = mct_aVect_indexRA(SDAT%avRLB(nu),trim(uname))
        vvar = mct_aVect_indexRA(SDAT%avRLB(nv),trim(vname))
        do i = 1,lsizeR
           avRV%rAttr(1,i) =  SDAT%avRLB(nu)%rAttr(uvar,i) * cos(xlon(i))  &
                             -SDAT%avRLB(nv)%rAttr(vvar,i) * sin(xlon(i))
           avRV%rAttr(2,i) =  SDAT%avRLB(nu)%rAttr(uvar,i) * sin(xlon(i))  &
                             +SDAT%avRLB(nv)%rAttr(vvar,i) * cos(xlon(i))
        enddo
        call mct_sMat_avMult(avRV,SDAT%sMatPs(nu),avFV)
! ---   don't need to recompute uvar and vvar, should be the same
!       uvar = mct_aVect_indexRA(SDAT%avFLB(nu),trim(uname))
!       vvar = mct_aVect_indexRA(SDAT%avFLB(nv),trim(vname))
        do i = 1,lsizeF
           SDAT%avFLB(nu)%rAttr(uvar,i) =  avFV%rAttr(1,i) * cos(ylon(i))  &
                                          +avFV%rAttr(2,i) * sin(ylon(i))
           SDAT%avFLB(nv)%rAttr(vvar,i) = -avFV%rAttr(1,i) * sin(ylon(i))  &
                                          +avFV%rAttr(2,i) * cos(ylon(i))
        enddo

        !--- map UB ---

        uvar = mct_aVect_indexRA(SDAT%avRUB(nu),trim(uname))
        vvar = mct_aVect_indexRA(SDAT%avRUB(nv),trim(vname))
        do i = 1,lsizeR
           avRV%rAttr(1,i) =  SDAT%avRUB(nu)%rAttr(uvar,i) * cos(xlon(i))  &
                             -SDAT%avRUB(nv)%rAttr(vvar,i) * sin(xlon(i))
           avRV%rAttr(2,i) =  SDAT%avRUB(nu)%rAttr(uvar,i) * sin(xlon(i))  &
                             +SDAT%avRUB(nv)%rAttr(vvar,i) * cos(xlon(i))
        enddo
        call mct_sMat_avMult(avRV,SDAT%sMatPs(nu),avFV)
! ---   don't need to recompute uvar and vvar, should be the same
!       uvar = mct_aVect_indexRA(SDAT%avFUB(nu),trim(uname))
!       vvar = mct_aVect_indexRA(SDAT%avFUB(nv),trim(vname))
        do i = 1,lsizeF
           SDAT%avFUB(nu)%rAttr(uvar,i) =  avFV%rAttr(1,i) * cos(ylon(i))  &
                                          +avFV%rAttr(2,i) * sin(ylon(i))
           SDAT%avFUB(nv)%rAttr(vvar,i) = -avFV%rAttr(1,i) * sin(ylon(i))  &
                                          +avFV%rAttr(2,i) * cos(ylon(i))
        enddo

        call mct_aVect_clean(avRV)
        call mct_aVect_clean(avFV)
        deallocate(xlon,ylon)

        call t_stopf(trim(lstr)//trim(timname)//'_vect')
     endif
  enddo

  do n = 1,SDAT%nstreams

     !--- method: coszen -------------------------------------------------------
     if (trim(SDAT%tintalgo(n)) == 'coszen') then
        call t_startf(trim(lstr)//trim(timname)//'_coszen')

        !--- make sure orb info has been set ---
        if (SDAT%eccen == SHR_ORB_UNDEF_REAL) then
           call shr_sys_abort(subname//' ERROR in orb params for coszen tinterp')
        else if (SDAT%modeldt < 1) then
           call shr_sys_abort(subname//' ERROR: model dt < 1 for coszen tinterp')
        endif

        !--- allocate avg cosz array ---
        lsizeF = mct_aVect_lsize(SDAT%avFLB(n))
        allocate(tavCosz(lsizeF),cosz(lsizeF),lonr(lsizeF),latr(lsizeF))

        !--- get lat/lon data ---
        kf = mct_aVect_indexRA(SDAT%grid%data,'lat')
        latr(:) = SDAT%grid%data%rAttr(kf,:) * deg2rad
        kf = mct_aVect_indexRA(SDAT%grid%data,'lon')
        lonr(:) = SDAT%grid%data%rAttr(kf,:) * deg2rad

        call t_startf(trim(lstr)//trim(timname)//'_coszenC')
        cosz = 0.0_r8
        call shr_tInterp_getCosz(cosz,lonr,latr,ymdmod,todmod, &
             SDAT%eccen,SDAT%mvelpp,SDAT%lambm0,SDAT%obliqr,SDAT%stream(n)%calendar)
        call t_stopf(trim(lstr)//trim(timname)//'_coszenC')

        if (newdata(n)) then
           !--- compute a new avg cosz ---
           call t_startf(trim(lstr)//trim(timname)//'_coszenN')
           call shr_tInterp_getAvgCosz(tavCosz,lonr,latr, &
                SDAT%ymdLB(n),SDAT%todLB(n), SDAT%ymdUB(n),SDAT%todUB(n), &
                SDAT%eccen,SDAT%mvelpp,SDAT%lambm0,SDAT%obliqr,SDAT%modeldt,&
	        SDAT%stream(n)%calendar) 
           call mct_avect_importRAttr(SDAT%avCoszen(n),'tavCosz',tavCosz,lsizeF)
           call t_stopf(trim(lstr)//trim(timname)//'_coszenN')
        else
           !--- reuse existing avg cosz ---
           call mct_avect_exportRAttr(SDAT%avCoszen(n),'tavCosz',tavCosz)
        endif

        !--- t-interp is LB data normalized with this factor: cosz/tavCosz ---
        do i = 1,lsizeF
           if (cosz(i) > solZenMin) then
              SDAT%avs(n)%rAttr(:,i) = SDAT%avFLB(n)%rAttr(:,i)*cosz(i)/tavCosz(i) 
           else
              SDAT%avs(n)%rAttr(:,i) =  0._r8
           endif
        enddo
        deallocate(tavCosz,cosz,lonr,latr)
        call t_stopf(trim(lstr)//trim(timname)//'_coszen')

     !--- method: not coszen ---------------------------------------------------
     elseif (trim(SDAT%tintalgo(n)) /= trim(shr_strdata_nullstr)) then

        call t_startf(trim(lstr)//trim(timname)//'_tint')
        call shr_tInterp_getFactors(SDAT%ymdlb(n),SDAT%todlb(n),SDAT%ymdub(n),SDAT%todub(n), &
                                    ymdmod,todmod,flb,fub, &
                                    calendar=SDAT%stream(n)%calendar,algo=trim(SDAT%tintalgo(n)))
        SDAT%avs(n)%rAttr(:,:) = SDAT%avFLB(n)%rAttr(:,:)*flb + SDAT%avFUB(n)%rAttr(:,:)*fub
        call t_stopf(trim(lstr)//trim(timname)//'_tint')

     else
        call t_startf(trim(lstr)//trim(timname)//'_zero')
        call mct_avect_zero(SDAT%avs(n))
        call t_stopf(trim(lstr)//trim(timname)//'_zero')
     endif
  enddo

  deallocate(newData)

  endif    ! nstreams > 0
  
  if (.not.ltimers) call t_adj_detailf(-tadj)

  end subroutine shr_strdata_advance

!===============================================================================
  subroutine shr_strdata_clean(SDAT)

  implicit none

  type(shr_strdata_type),intent(inout) :: SDAT

  integer(IN) :: n

   !----- formats -----
  character(len=*),parameter :: subname = "(shr_strdata_clean) "

!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------

  if (SDAT%nxg * SDAT%nyg == 0) then
     return
  endif

  SDAT%nxg = 0
  SDAT%nyg = 0
  SDAT%strnxg = 0
  SDAT%strnyg = 0

  SDAT%nstreams = 0
  SDAT%nvectors = 0
  SDAT%ustrm = 0
  SDAT%vstrm = 0

  SDAT%dofill = .false.
  SDAT%domaps = .false.

  call mct_ggrid_clean(SDAT%grid)
  call mct_gsmap_clean(SDAT%gsmap)
  do n = 1,nStrMax
     ! need clean SDAT%stream(n) method
     call mct_avect_clean(SDAT%avs(n))
     call mct_avect_clean(SDAT%avRLB(n))
     call mct_avect_clean(SDAT%avRUB(n))
     call mct_avect_clean(SDAT%avFLB(n))
     call mct_avect_clean(SDAT%avFUB(n))
     call mct_ggrid_clean(SDAT%gridR(n))
     call mct_sMatP_clean(SDAT%sMatPf(n))
     call mct_sMatP_clean(SDAT%sMatPs(n))
     call mct_gsmap_clean(SDAT%gsmapR(n))
  enddo

  end subroutine shr_strdata_clean

!===============================================================================
!===============================================================================
  subroutine shr_strdata_restWrite(filename,SDAT,mpicom,str1,str2)

  implicit none

  character(len=*)      ,intent(in)    :: filename
  type(shr_strdata_type),intent(inout) :: SDAT
  integer(IN)           ,intent(in)    :: mpicom
  character(len=*)      ,intent(in)    :: str1
  character(len=*)      ,intent(in)    :: str2

  !--- local ----
  type(shr_stream_streamtype),pointer :: streams(:)
  integer(IN) :: n,my_task,ier

   !----- formats -----
  character(len=*),parameter :: subname = "(shr_strdata_restWrite) "

!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------

  call MPI_COMM_RANK(mpicom,my_task,ier)

  if (my_task == 0) then
     call shr_stream_restWrite(SDAT%stream,trim(filename),trim(str1),trim(str2),SDAT%nstreams)
  endif

  end subroutine shr_strdata_restWrite

!===============================================================================
!===============================================================================
  subroutine shr_strdata_restRead(filename,SDAT,mpicom)

  implicit none

  character(len=*)      ,intent(in)    :: filename
  type(shr_strdata_type),intent(inout) :: SDAT
  integer(IN)           ,intent(in)    :: mpicom

  !--- local ----
  type(shr_stream_streamtype),pointer :: streams(:)
  integer(IN) :: n,my_task,ier

   !----- formats -----
  character(len=*),parameter :: subname = "(shr_strdata_restRead) "

!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------

  call MPI_COMM_RANK(mpicom,my_task,ier)

  if (my_task == 0) then
     call shr_stream_restRead(SDAT%stream,trim(filename),SDAT%nstreams)
  endif

  end subroutine shr_strdata_restRead

!===============================================================================
!===============================================================================
  subroutine shr_strdata_setOrbs(SDAT,eccen,mvelpp,lambm0,obliqr,modeldt)

  implicit none

  type(shr_strdata_type),intent(inout) :: SDAT
  real(R8),intent(in) :: eccen
  real(R8),intent(in) :: mvelpp
  real(R8),intent(in) :: lambm0
  real(R8),intent(in) :: obliqr
  integer(IN),intent(in) :: modeldt

  !----- formats -----
  character(len=*),parameter :: subname = "(shr_strdata_setOrbs) "

!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------

  SDAT%eccen   = eccen
  SDAT%mvelpp  = mvelpp
  SDAT%lambm0  = lambm0
  SDAT%obliqr  = obliqr
  SDAT%modeldt = modeldt

  end subroutine shr_strdata_setOrbs

!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_strdata_readnml -- read control strdata
!
! !DESCRIPTION:
!     Reads strdata common to all data models
!
! !REVISION HISTORY:
!     2004-Dec-15 - J. Schramm - first version
!     2009-Apr-16 - T. Craig - add minimal parallel support
!
! !INTERFACE: ------------------------------------------------------------------

subroutine shr_strdata_readnml(SDAT,file,rc,mpicom)

   implicit none

! !INPUT/OUTPUT PARAMETERS: 

   type(shr_strdata_type),intent(inout):: SDAT  ! strdata data data-type
   character(*),optional ,intent(in)   :: file ! file to read strdata from
   integer(IN),optional  ,intent(out)  :: rc   ! return code
   integer(IN),optional  ,intent(in)   :: mpicom ! mpi comm

!EOP 

   integer(IN)    :: rCode         ! return code
   integer(IN)    :: nUnit         ! fortran i/o unit number
   integer(IN)    :: n             ! generic loop index
   integer(IN)    :: my_task       ! my task number, 0 is default
   integer(IN)    :: master_task   ! master task number, 0 is default
   integer(IN)    :: ntasks        ! total number of tasks

   !----- temporary/local namelist vars to read int -----
   character(CL) :: dataMode          ! flags physics options wrt input data
   character(CL) :: domainFile        ! file   containing domain info
   character(CL) :: streams(nStrMax)  ! stream description file names
   character(CL) :: taxMode(nStrMax)  ! time axis cycling mode
   real(R8)      :: dtlimit(nStrMax)  ! delta time limiter
   character(CL) :: vectors(nVecMax)  ! define vectors to vector map
   character(CL) :: fillalgo(nStrMax) ! fill algorithm
   character(CL) :: fillmask(nStrMax) ! fill mask
   character(CL) :: fillread(nStrMax) ! fill mapping file to read
   character(CL) :: fillwrite(nStrMax)! fill mapping file to write
   character(CL) :: mapalgo(nStrMax)  ! scalar map algorithm
   character(CL) :: mapmask(nStrMax)  ! scalar map mask
   character(CL) :: mapread(nStrMax)  ! regrid mapping file to read
   character(CL) :: mapwrite(nStrMax) ! regrid mapping file to write
   character(CL) :: tintalgo(nStrMax) ! time interpolation algorithm
   character(CL) :: io_type
   integer(IN)   :: num_iotasks
   integer(IN)   :: io_root
   integer(IN)   :: io_stride
   integer(IN)   :: num_agg
   character(CL) :: fileName    ! generic file name
   integer(IN)   :: yearFirst   ! first year to use in data stream
   integer(IN)   :: yearLast    ! last  year to use in data stream
   integer(IN)   :: yearAlign   ! data year that aligns with yearFirst

   !----- define namelist -----
   namelist / shr_strdata_nml / &
        dataMode        &
      , domainFile      &
      , streams         &
      , taxMode         &
      , dtlimit         &
      , vectors         &
      , fillalgo        &
      , fillmask        &
      , fillread        &
      , fillwrite       &
      , mapalgo         &
      , mapmask         &
      , mapread         &
      , mapwrite        &
      , tintalgo        
   !----- formats -----
   character(*),parameter :: subName = "(shr_strdata_readnml) " 
   character(*),parameter ::   F00 = "('(shr_strdata_readnml) ',8a)" 
   character(*),parameter ::   F01 = "('(shr_strdata_readnml) ',a,i6,a)" 
   character(*),parameter ::   F02 = "('(shr_strdata_readnml) ',a,es13.6)" 
   character(*),parameter ::   F03 = "('(shr_strdata_readnml) ',a,l6)" 
   character(*),parameter ::   F04 = "('(shr_strdata_readnml) ',a,i2,a,a)" 
   character(*),parameter ::   F20 = "('(shr_strdata_readnml) ',a,i6,a)" 
   character(*),parameter ::   F90 = "('(shr_strdata_readnml) ',58('-'))"

!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------

   if (present(rc)) rc = 0

   my_task = 0
   master_task = 0
   ntasks = 1
   if (present(mpicom)) then
      call MPI_COMM_RANK(mpicom,my_task,rCode)
      call MPI_COMM_SIZE(mpicom,ntasks,rCode)
   endif

!--master--task--
   if (my_task == master_task) then

   !----------------------------------------------------------------------------
   ! set default values for namelist vars
   !----------------------------------------------------------------------------
   dataMode    = 'NULL'        
   domainFile  = trim(shr_strdata_nullstr)        
   streams(:)  = trim(shr_strdata_nullstr)
   taxMode(:)  = trim(shr_stream_taxis_cycle)
   dtlimit(:)  = dtlimit_default
   vectors(:)  = trim(shr_strdata_nullstr)
   fillalgo(:) = 'nn'
   fillmask(:) = 'nomask'
   fillread(:) = trim(shr_strdata_unset)
   fillwrite(:)= trim(shr_strdata_unset)
   mapalgo(:)  = 'bilinear'
   mapmask(:)  = 'dstmask'
   mapread(:)  = trim(shr_strdata_unset)
   mapwrite(:) = trim(shr_strdata_unset)
   tintalgo(:) = 'linear'


   !----------------------------------------------------------------------------
   ! read input namelist
   !----------------------------------------------------------------------------
   if (present(file)) then
      write(logunit,F00) 'reading input namelist file: ',trim(file)
      call shr_sys_flush(logunit)
      nUnit = shr_file_getUnit() ! get unused fortran i/o unit number
      open (nUnit,file=trim(file),status="old",action="read")
      read (nUnit,nml=shr_strdata_nml,iostat=rCode)
      close(nUnit)
      call shr_file_freeUnit(nUnit)
      if (rCode > 0) then
         write(logunit,F01) 'ERROR: reading input namelist, '//trim(file)//' iostat=',rCode
         call shr_sys_abort(subName//": namelist read error "//trim(file))
      end if
   endif

   !----------------------------------------------------------------------------
   ! copy temporary/local namelist vars into data structure
   !----------------------------------------------------------------------------
   SDAT%nstreams    = 0
   do n=1,nStrMax
      call shr_stream_default(SDAT%stream(n))
   enddo
   SDAT%dataMode    = dataMode  
   SDAT%domainFile  = domainFile
   SDAT%streams(:)  = streams(:)    
   SDAT%taxMode(:)  = taxMode(:)
   SDAT%dtlimit(:)  = dtlimit(:)
   SDAT%vectors(:)  = vectors(:)    
   SDAT%fillalgo(:) = fillalgo(:)    
   SDAT%fillmask(:) = fillmask(:)    
   SDAT%fillread(:) = fillread(:)    
   SDAT%fillwrit(:) = fillwrite(:)    
   SDAT%mapalgo(:)  = mapalgo(:)    
   SDAT%mapmask(:)  = mapmask(:)    
   SDAT%mapread(:)  = mapread(:)    
   SDAT%mapwrit(:)  = mapwrite(:)    
   SDAT%tintalgo(:) = tintalgo(:)    
   do n=1,nStrMax
      if (trim(streams(n)) /= trim(shr_strdata_nullstr)) SDAT%nstreams = max(SDAT%nstreams,n)
      if (trim(SDAT%taxMode(n)) == trim(shr_stream_taxis_extend)) SDAT%dtlimit(n) = 1.0e30
   end do
   SDAT%nvectors = 0
   do n=1,nVecMax
      if (trim(vectors(n)) /= trim(shr_strdata_nullstr)) SDAT%nvectors = n
   end do

   do n = 1,SDAT%nstreams
      call shr_stream_parseInput(SDAT%streams(n),fileName,yearAlign,yearFirst,yearLast)
      call shr_stream_init(SDAT%stream(n),fileName,yearFirst,yearLast,yearAlign, &
                   trim(SDAT%taxMode(n)))
   enddo

!   call shr_strdata_print(SDAT,trim(file)//' NML_ONLY')

   endif   ! master_task
!--master--task--

   if (present(mpicom)) then
      call shr_strdata_bcastnml(SDAT,mpicom)
   endif

   SDAT%ymdLB = -1
   SDAT%todLB = -1
   SDAT%ymdUB = -1
   SDAT%todUB = -1
   SDAT%dtmin = 1.0e30
   SDAT%dtmax = 0.0
   SDAT%nxg   = 0
   SDAT%nyg   = 0
   SDAT%eccen  = SHR_ORB_UNDEF_REAL
   SDAT%mvelpp = SHR_ORB_UNDEF_REAL
   SDAT%lambm0 = SHR_ORB_UNDEF_REAL
   SDAT%obliqr = SHR_ORB_UNDEF_REAL
   SDAT%modeldt = 0
   SDAT%calendar = shr_cal_noleap

end subroutine shr_strdata_readnml

!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_strdata_pioinit -- initialize pio layer
!
! !DESCRIPTION:
!     Initialize PIO for a component model
!
! !REVISION HISTORY:
!     2010-10-26    Jim Edwards
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_strdata_pioinit(SDAT,io_subsystem, io_type )
  type(shr_strdata_type),intent(inout):: SDAT  ! strdata data data-type
  type(iosystem_desc_t), pointer :: io_subsystem
  integer, intent(in) :: io_type

  SDAT%pio_subsystem => io_subsystem
  SDAT%io_type=io_type

end subroutine shr_strdata_pioinit

!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_strdata_create -- set strdata and stream info from interface
!
! !DESCRIPTION:
!     Set strdata and stream info from fortran interface.
!     Note: When this is called, previous settings are reset to defaults
!           and then the values passed are used.
!
! !REVISION HISTORY:
!     2004-Dec-15 - J. Schramm - first version
!     2009-Apr-16 - T. Craig - add minimal parallel support
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_strdata_create(SDAT, name, mpicom, compid, gsmap, ggrid, nxg, nyg, &
!--- streams stuff required ---
           yearFirst, yearLast, yearAlign, offset,          &
           domFilePath, domFileName,                        &
           domTvarName, domXvarName, domYvarName, domAreaName, domMaskName, &
           filePath, filename, fldListFile, fldListModel,   &
           pio_subsystem, pio_iotype,                       &
!--- strdata optional ---
           taxMode, dtlimit, tintalgo,                      &
           fillalgo, fillmask, fillread, fillwrite,         &
           mapalgo, mapmask, mapread, mapwrite,             &
           calendar)

   implicit none

! !INPUT/OUTPUT PARAMETERS: 

   type(shr_strdata_type),intent(inout):: SDAT  ! strdata data data-type
   character(*)          ,intent(in)   :: name  ! name of strdata
   integer(IN)           ,intent(in)   :: mpicom ! mpi comm
   integer(IN)           ,intent(in)   :: compid
   type(mct_gsmap)       ,intent(in)   :: gsmap
   type(mct_ggrid)       ,intent(in)   :: ggrid
   integer(IN)           ,intent(in)   :: nxg
   integer(IN)           ,intent(in)   :: nyg

   integer(IN)           ,intent(in)   :: yearFirst ! first year to use 
   integer(IN)           ,intent(in)   :: yearLast  ! last  year to use 
   integer(IN)           ,intent(in)   :: yearAlign ! align yearFirst with this model year
   integer(IN)           ,intent(in)   :: offset    ! offset in seconds of stream data
   character(*)          ,intent(in)   :: domFilePath  ! domain file path
   character(*)          ,intent(in)   :: domFileName  ! domain file name
   character(*)          ,intent(in)   :: domTvarName  ! domain time dim name
   character(*)          ,intent(in)   :: domXvarName  ! domain x dim name
   character(*)          ,intent(in)   :: domYvarName  ! domain y dim nam
   character(*)          ,intent(in)   :: domAreaName  ! domain area name
   character(*)          ,intent(in)   :: domMaskName  ! domain mask name
   character(*)          ,intent(in)   :: filePath     ! path to filenames
   character(*)          ,intent(in)   :: filename(:)  ! filename for index filenumber
   character(*)          ,intent(in)   :: fldListFile  ! file field names, colon delim list
   character(*)          ,intent(in)   :: fldListModel ! model field names, colon delim list
   type(iosystem_desc_t), pointer      :: pio_subsystem ! PIO subsystem pointer
   integer(IN)          , intent(in)   :: pio_iotype    ! PIO file type

   character(*),optional ,intent(in)   :: taxMode
   real(R8)    ,optional ,intent(in)   :: dtlimit
   character(*),optional ,intent(in)   :: fillalgo  ! fill algorithm
   character(*),optional ,intent(in)   :: fillmask  ! fill mask
   character(*),optional ,intent(in)   :: fillread  ! fill mapping file to read
   character(*),optional ,intent(in)   :: fillwrite ! fill mapping file to write
   character(*),optional ,intent(in)   :: mapalgo   ! scalar map algorithm
   character(*),optional ,intent(in)   :: mapmask   ! scalar map mask
   character(*),optional ,intent(in)   :: mapread   ! regrid mapping file to read
   character(*),optional ,intent(in)   :: mapwrite  ! regrid mapping file to write
   character(*),optional ,intent(in)   :: tintalgo  ! time interpolation algorithm
   character(*),optional, intent(in)   :: calendar

!EOP 

!  --- local ---
!  --- formats ---
   character(*),parameter :: subName = "(shr_strdata_create) " 
   character(*),parameter ::   F00 = "('(shr_strdata_create) ',8a)" 

!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------

   call shr_strdata_readnml(SDAT,mpicom=mpicom)
   
   SDAT%nstreams = 1

   call shr_strdata_pioinit(sdat, pio_subsystem, pio_iotype)

   if (present(taxMode)) then
      SDAT%taxMode(1) = taxMode
      if (trim(SDAT%taxMode(1)) == trim(shr_stream_taxis_extend)) SDAT%dtlimit(1) = 1.0e30
   endif
   if (present(dtlimit)) then
      SDAT%dtlimit(1) = dtlimit
   endif
   if (present(fillalgo)) then
      SDAT%fillalgo(1) = fillalgo
   endif
   if (present(fillmask)) then
      SDAT%fillmask(1) = fillmask
   endif
   if (present(fillread)) then
      SDAT%fillread(1) = fillread
   endif
   if (present(fillwrite)) then
      SDAT%fillwrit(1) = fillwrite
   endif
   if (present(mapalgo)) then
      SDAT%mapalgo(1) = mapalgo
   endif
   if (present(mapmask)) then
      SDAT%mapmask(1) = mapmask
   endif
   if (present(mapread)) then
      SDAT%mapread(1) = mapread
   endif
   if (present(mapwrite)) then
      SDAT%mapwrit(1) = mapwrite
   endif
   if (present(tintalgo)) then
      SDAT%tintalgo(1) = tintalgo
   endif
   if (present(mapmask)) then
      SDAT%mapmask(1) = mapmask
   endif
   if (present(calendar)) then
     SDAT%calendar = trim(shr_cal_calendarName(trim(calendar)))
   endif

   call shr_stream_set(SDAT%stream(1),yearFirst,yearLast,yearAlign,offset,taxMode, &
                          fldListFile,fldListModel,domFilePath,domFileName, &
                          domTvarName,domXvarName,domYvarName,domAreaName,domMaskName, &
                          filePath,filename,trim(name))

   call shr_strdata_init(SDAT, mpicom, compid, &
        gsmap=gsmap, ggrid=ggrid, nxg=nxg, nyg=nyg)

end subroutine shr_strdata_create

!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_strdata_print -- read control strdata
!
! !DESCRIPTION:
!     Reads strdata common to all data models
!
! !REVISION HISTORY:
!     2004-Dec-15 - J. Schramm - first version
!     2009-Apr-16 - T. Craig - add minimal parallel support
!
! !INTERFACE: ------------------------------------------------------------------

subroutine shr_strdata_print(SDAT,name)

   implicit none

! !INPUT/OUTPUT PARAMETERS: 

   type(shr_strdata_type)  ,intent(in) :: SDAT  ! strdata data data-type
   character(len=*),optional,intent(in) :: name  ! just a name for tracking

!EOP 

   integer(IN)   :: n
   character(CL) :: lname

   !----- formats -----
   character(*),parameter :: subName = "(shr_strdata_print) " 
   character(*),parameter ::   F00 = "('(shr_strdata_print) ',8a)" 
   character(*),parameter ::   F01 = "('(shr_strdata_print) ',a,i6,a)" 
   character(*),parameter ::   F02 = "('(shr_strdata_print) ',a,es13.6)" 
   character(*),parameter ::   F03 = "('(shr_strdata_print) ',a,l6)" 
   character(*),parameter ::   F04 = "('(shr_strdata_print) ',a,i2,a,a)" 
   character(*),parameter ::   F05 = "('(shr_strdata_print) ',a,i2,a,i6)" 
   character(*),parameter ::   F06 = "('(shr_strdata_print) ',a,i2,a,l2)" 
   character(*),parameter ::   F07 = "('(shr_strdata_print) ',a,i2,a,es13.6)" 
   character(*),parameter ::   F20 = "('(shr_strdata_print) ',a,i6,a)" 
   character(*),parameter ::   F90 = "('(shr_strdata_print) ',58('-'))"

!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------

   lname = 'unknown'
   if (present(name)) then
      lname = trim(name)
   endif
   !----------------------------------------------------------------------------
   ! document datatype settings
   !----------------------------------------------------------------------------
   write(logunit,F90)
   write(logunit,F00) "name        = ",trim(lname)
   write(logunit,F00) "dataMode    = ",trim(SDAT%dataMode)
   write(logunit,F00) "domainFile  = ",trim(SDAT%domainFile)
   write(logunit,F01) "nxg         = ",SDAT%nxg
   write(logunit,F01) "nyg         = ",SDAT%nyg
   write(logunit,F00) "calendar    = ",trim(SDAT%calendar)
   write(logunit,F01) "io_type     = ",SDAT%io_type
   write(logunit,F02) "eccen       = ",SDAT%eccen
   write(logunit,F02) "mvelpp      = ",SDAT%mvelpp
   write(logunit,F02) "lambm0      = ",SDAT%lambm0
   write(logunit,F02) "obliqr      = ",SDAT%obliqr
   write(logunit,F01) "nstreams    = ",SDAT%nstreams
   write(logunit,F01) "pio_iotype  = ",sdat%io_type

   do n=1, SDAT%nstreams
     write(logunit,F04) "  streams (",n,") = ",trim(SDAT%streams(n))
     write(logunit,F04) "  taxMode (",n,") = ",trim(SDAT%taxMode(n))
     write(logunit,F07) "  dtlimit (",n,") = ",SDAT%dtlimit(n)
     write(logunit,F05) "  strnxg  (",n,") = ",SDAT%strnxg(n)
     write(logunit,F05) "  strnyg  (",n,") = ",SDAT%strnyg(n)
     write(logunit,F06) "  dofill  (",n,") = ",SDAT%dofill(n)
     write(logunit,F04) "  fillalgo(",n,") = ",trim(SDAT%fillalgo(n))
     write(logunit,F04) "  fillmask(",n,") = ",trim(SDAT%fillmask(n))
     write(logunit,F04) "  fillread(",n,") = ",trim(SDAT%fillread(n))
     write(logunit,F04) "  fillwrit(",n,") = ",trim(SDAT%fillwrit(n))
     write(logunit,F06) "  domaps  (",n,") = ",SDAT%domaps(n)
     write(logunit,F04) "  mapalgo (",n,") = ",trim(SDAT%mapalgo(n))
     write(logunit,F04) "  mapmask (",n,") = ",trim(SDAT%mapmask(n))
     write(logunit,F04) "  mapread (",n,") = ",trim(SDAT%mapread(n))
     write(logunit,F04) "  mapwrit (",n,") = ",trim(SDAT%mapwrit(n))
     write(logunit,F04) "  tintalgo(",n,") = ",trim(SDAT%tintalgo(n))
     write(logunit,F01) " "
   end do
   write(logunit,F01) "nvectors    = ",SDAT%nvectors
   do n=1, SDAT%nvectors
     write(logunit,F04) "  vectors (",n,") = ",trim(SDAT%vectors(n))
   end do
   write(logunit,F90)
   call shr_sys_flush(logunit)

end subroutine shr_strdata_print

!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_strdata_bcastnml -- broadcast control strdata
!
! !DESCRIPTION:
!     Broadcast strdata
!
! !REVISION HISTORY:
!     2009-Apr-16 - T. Craig - first version
!
! !INTERFACE: ------------------------------------------------------------------

subroutine shr_strdata_bcastnml(SDAT,mpicom,rc)

   use shr_mpi_mod, only : shr_mpi_bcast

   implicit none

! !INPUT/OUTPUT PARAMETERS: 

   type(shr_strdata_type),intent(inout) :: SDAT  ! strdata data data-type
   integer(IN)           ,intent(in)  :: mpicom ! mpi communicator
   integer(IN),optional  ,intent(out) :: rc   ! return code

!EOP 

   !----- local -----
   integer(IN) :: lrc

   !----- formats -----
   character(*),parameter :: subName = "(shr_strdata_bcastnml) " 

!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------

   lrc = 0

   call shr_mpi_bcast(SDAT%dataMode  ,mpicom,'dataMode')
   call shr_mpi_bcast(SDAT%domainFile,mpicom,'domainFile')
   call shr_mpi_bcast(SDAT%calendar  ,mpicom,'calendar')
   call shr_mpi_bcast(SDAT%nstreams  ,mpicom,'nstreams')
   call shr_mpi_bcast(SDAT%nvectors  ,mpicom,'nvectors')
   call shr_mpi_bcast(SDAT%streams   ,mpicom,'streams')
   call shr_mpi_bcast(SDAT%taxMode   ,mpicom,'taxMode')
   call shr_mpi_bcast(SDAT%dtlimit   ,mpicom,'dtlimit')
   call shr_mpi_bcast(SDAT%vectors   ,mpicom,'vectors')
   call shr_mpi_bcast(SDAT%fillalgo  ,mpicom,'fillalgo')
   call shr_mpi_bcast(SDAT%fillmask  ,mpicom,'fillmask')
   call shr_mpi_bcast(SDAT%fillread  ,mpicom,'fillread')
   call shr_mpi_bcast(SDAT%fillwrit  ,mpicom,'fillwrit')
   call shr_mpi_bcast(SDAT%mapalgo   ,mpicom,'mapalgo')
   call shr_mpi_bcast(SDAT%mapmask   ,mpicom,'mapmask')
   call shr_mpi_bcast(SDAT%mapread   ,mpicom,'mapread')
   call shr_mpi_bcast(SDAT%mapwrit   ,mpicom,'mapwrit')
   call shr_mpi_bcast(SDAT%tintalgo  ,mpicom,'tintalgo')

   if (present(rc)) then
      rc = lrc
   endif

end subroutine shr_strdata_bcastnml

!===============================================================================
 
subroutine shr_strdata_setlogunit(nu)

  integer(IN),intent(in) :: nu
  character(len=*),parameter :: subname = "(shr_strdata_setlogunit) "

  ! tcx DOES NOTHING, REMOVE

end subroutine shr_strdata_setlogunit

!===============================================================================
!===============================================================================

end module shr_strdata_mod

